﻿using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ZerAx.ObjectNotation
{
    public class ZonCompound : Zon
    {
        public override ZonType Type => ZonType.Compound;

        public readonly Dictionary<string, Zon> data;

        public Zon this[string childName] => data.TryGetValue(childName, out var value) ? value : null;

        public ZonCompound()
        {
            data = new();
        }

        public ZonCompound(IEnumerable<KeyValuePair<string, Zon>> children)
        {
            data = new(children);
        }

        public ZonCompound(params (string, Zon)[] children) : this(children.Select(x => new KeyValuePair<string, Zon>(x.Item1, x.Item2))) { }

        public void AddChild(string tag, Zon child)
        {
            data.Add(tag, child);
        }

        public void AddChild(ZonTagged tagged)
        {
            data.Add(tagged.tag, tagged.data);
        }

        public ZonCompound With(string tag, Zon child)
        {
            data.Add(tag, child);
            return this;
        }

        public bool? GetBool(string childName) => this[childName].AsBool();
        public byte? GetU8(string childName) => this[childName].AsU8();
        public int? GetI32(string childName) => this[childName].AsI32();
        public float? GetF32(string childName) => this[childName].AsF32();
        public (float x, float y, float z)? GetVec3(string childName) => this[childName].AsVec3();
        public (int x, int y, int z)? GetVec3i(string childName) => this[childName].AsVec3i();
        public string GetString(string childName) => this[childName].AsString();
        public ZonCompound GetCompound(string childName) => this[childName] as ZonCompound;

        public override void Initialize(BinaryReader reader)
        {
            data.Clear();
            int count = reader.ReadInt32();
            for (int i = 0; i < count; i++)
            {
                var name = reader.ReadString();
                var value = Deserialze(reader);
                data.Add(name, value);
            }
        }

        public override void SerializeData(BinaryWriter writer)
        {
            writer.Write(data.Count);
            foreach (var (name, obj) in data)
            {
                writer.Write(name);
                obj.Serialize(writer);
            }
        }

        public override string ToString()
        {
            return $"{{{string.Join(',', data.Select(x => $"\"{x.Key}\":{x.Value}"))}}}";
        }
    }
}
